package com.guaniu.voip.utils;

import android.app.usage.StorageStatsManager;
import android.content.Context;
import android.graphics.Point;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.WindowManager;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.text.DecimalFormat;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.Properties;

import static android.content.Context.STORAGE_STATS_SERVICE;

public final class DeviceUtil {
    private final static String TAG = "DeviceUtil";
    private final static String UNKNOWN = "unknown";

    /**
     * Return Cpu information
     *
     * @return Cpu info
     */
    public static String getCpuInfo() {
        String result = UNKNOWN;
        try {
            String[] args = {"/system/bin/cat", "/proc/cpuinfo"};
            ProcessBuilder cmd = new ProcessBuilder(args);
            Process process = cmd.start();
            StringBuilder sb = new StringBuilder();
            String readLine;
            BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
            while ((readLine = responseReader.readLine()) != null) {
                if (readLine.startsWith("Hardware")) {
                    result = readLine.substring(readLine.indexOf(':')+1).trim();
                    break;
                }
            }
            responseReader.close();
        } catch (IOException ignored) {
        }
        return result;
    }

    public static float getCpuUsage() {
        // 存放CPU使用信息的数组
        long[] cpuInfo = new long[8];

        try {
            String[] args = {"/system/bin/cat", "/proc/stat"};
            ProcessBuilder cmd = new ProcessBuilder(args);
            Process process = cmd.start();
            BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
            String readLine = responseReader.readLine();
            if (TextUtils.isEmpty(readLine) ) {
                return -1f;
            }

            // 按空格拆分数据
            String[] split = readLine.split(" ");
            // 保存CPU使用信息
            for (int i = 0; i < cpuInfo.length; i++) {
                cpuInfo[i] = Long.parseLong(split[i + 2]);
            }

            // 计算用户态和内核态CPU使用时间
            long userTime = cpuInfo[0];
            long niceTime = cpuInfo[1];
            long systemTime = cpuInfo[2];
            long idleTime = cpuInfo[3];

            // 计算总CPU使用时间
            long totalCpuTime = userTime + niceTime + systemTime + idleTime;

            // 计算CPU使用率
            float cpuUsage = 1.0f - ((float) idleTime / totalCpuTime);
            Log.i(TAG, "getCpuUsage: "+cpuUsage);

            return cpuUsage;
        } catch (IOException e) {
            e.printStackTrace();
        }

        return 0f;
    }

    /**
     * Return Cpu information
     *
     * @return Cpu info
     */
    public static String getMemTotal() {
        String result = UNKNOWN;
        try {
            String[] args = {"/system/bin/cat", "/proc/meminfo"};
            ProcessBuilder cmd = new ProcessBuilder(args);
            Process process = cmd.start();
            String readLine;
            String memTotal = "";
            String memAvailable = "";
            BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
            while ((readLine = responseReader.readLine()) != null) {
                if (readLine.startsWith("MemTotal")) {
                    memTotal = readLine.substring(readLine.indexOf(':')+1, readLine.indexOf("kB")-1).trim();
                }
            }
            responseReader.close();
            result = formatStorageSize(Long.parseLong(memTotal)*1024);
        } catch (IOException ignored) {
        }
        return result;
    }

    public static String getMemAvailable() {
        String result = UNKNOWN;
        try {
            String[] args = {"/system/bin/cat", "/proc/meminfo"};
            ProcessBuilder cmd = new ProcessBuilder(args);
            Process process = cmd.start();
            String readLine;
            String memAvailable = "";
            BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
            while ((readLine = responseReader.readLine()) != null) {
                if (readLine.startsWith("MemAvailable")) {
                    memAvailable = readLine.substring(readLine.indexOf(':')+1, readLine.indexOf("kB")-1).trim();
                }
            }
            responseReader.close();
            result = formatStorageSize(Long.parseLong(memAvailable)*1024);
        } catch (IOException ignored) {
        }
        return result;
    }

    public static String getMemInfo() {
        String result = UNKNOWN;
        try {
            String[] args = {"/system/bin/cat", "/proc/meminfo"};
            ProcessBuilder cmd = new ProcessBuilder(args);
            Process process = cmd.start();
            String readLine;
            String memTotal = "";
            String memAvailable = "";
            BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
            while ((readLine = responseReader.readLine()) != null) {
                if (readLine.startsWith("MemTotal")) {
                    memTotal = readLine.substring(readLine.indexOf(':')+1, readLine.indexOf("kB")-1).trim();
                } else if (readLine.startsWith("MemAvailable")) {
                    memAvailable = readLine.substring(readLine.indexOf(':')+1, readLine.indexOf("kB")-1).trim();
                }
            }
            responseReader.close();
            result = formatStorageSize(Long.parseLong(memTotal)*1024) + "/" + formatCommonSize(Long.parseLong(memAvailable)*1024);
        } catch (IOException ignored) {
        }
        return result;
    }


    public static String formatCommonSize(long fileSize) {
        DecimalFormat df = new DecimalFormat("#.0");
        String fileSizeString = "";
        String wrongSize = "0B";
        if (fileSize == 0) {
            return wrongSize;
        }
        if (fileSize < 1024) {
            fileSizeString = df.format((double) fileSize) + "B";
        } else if (fileSize < 1048576) {
            fileSizeString = df.format((double) fileSize / 1024) + "KB";
        } else if (fileSize < 1073741824) {
            fileSizeString = df.format((double) fileSize / 1048576) + "MB";
        } else {
            fileSizeString = df.format((double) fileSize / 1073741824) + "GB";
        }
        return fileSizeString;
    }

    private static String formatStorageSize(long fileSize) {
        float gbSize = fileSize*1f/1073741824;
        if (gbSize > 3690) {
            return "4TB";
        } else if (gbSize > 1840) {
            return "2TB";
        } else if (gbSize > 923) {
            return "1TB";
        } else if (gbSize > 460) {
            return "512 GB";
        } else if (gbSize > 235) {
            return "256 GB";
        } else if (gbSize > 115) {
            return "128 GB";
        } else if (gbSize > 57) {
            return "64 GB";
        } else if (gbSize > 28) {
            return "32 GB";
        } else if (gbSize > 14) {
            return "16 GB";
        } else if (gbSize > 7) {
            return "8 GB";
        } else if (gbSize > 3) {
            return "4 GB";
        } else if (gbSize > 1.5) {
            return "2 GB";
        } else {
            return "1 GB";
        }
    }

    /**
     * 内部总存储空间
     */
    public static String getStorageTotal() {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            StorageStatsManager storageStatsManager = null;
            storageStatsManager = (StorageStatsManager) Utils.getApp().getSystemService(STORAGE_STATS_SERVICE);
            try {
                return formatStorageSize(storageStatsManager.getTotalBytes(StorageManager.UUID_DEFAULT));
            } catch (IOException e) {
                e.printStackTrace();
            }
            return UNKNOWN;
        } else {
            //获取内部存储根目录
            File path = Environment.getDataDirectory();
            //系统的空间描述类
            StatFs stat = new StatFs(path.getPath());
            //每个区块占字节数
            long blockSize = stat.getBlockSizeLong();
            //区块总数
            long totalBlocks = stat.getBlockCountLong();

            return formatStorageSize(totalBlocks * blockSize);
        }
    }

    /**
     * 内部可用空间
     */
    public static String getStorageFree() {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            StorageStatsManager storageStatsManager = (StorageStatsManager) Utils.getApp().getSystemService(STORAGE_STATS_SERVICE);
            try {
                return formatCommonSize(storageStatsManager.getFreeBytes(StorageManager.UUID_DEFAULT));
            } catch (IOException e) {
                e.printStackTrace();
            }
            return UNKNOWN;
        } else {
            File path = Environment.getDataDirectory();
            StatFs stat = new StatFs(path.getPath());
            long blockSize = stat.getBlockSizeLong();
            //获取可用区块数量
            long availableBlocks = stat.getAvailableBlocksLong();
            return formatCommonSize(availableBlocks * blockSize);
        }
    }

    public static String getSerial() {
//        String szSerial = UNKNOWN;
//        try {
//            szSerial = getSystemProperty("ro.serialno"); //"ro.boot.serialno"
//            if (TextUtils.isEmpty(szSerial)) {
//                szSerial = Settings.Secure.getString(Utils.getApp().getContentResolver(), Settings.Secure.ANDROID_ID);
//            }
//        } catch (Exception e) {
//
//        }
//        return szSerial;
        return "75812969bec64b35";
    }

    public static String getModel() {
        return Build.MODEL;
    }

    public static String getRomVersion() {
        String ret = UNKNOWN;
        String propertyName = "ro.build.version.incremental";
        if (!TextUtils.isEmpty(propertyName)) {
            ret = getSystemProperty(propertyName);
        }
        if (TextUtils.isEmpty(ret) || ret.equals(UNKNOWN)) {
            try {
                String display = Build.DISPLAY;
                if (!TextUtils.isEmpty(display)) {
                    ret = display.toLowerCase();
                }
            } catch (Throwable ignore) {/**/}
        }
        if (TextUtils.isEmpty(ret)) {
            return UNKNOWN;
        }
        return ret;
    }

    public static Point getScreenSize() {
        WindowManager wm = (WindowManager) Utils.getApp().getSystemService(Context.WINDOW_SERVICE);
        if (wm == null) return null;
        Point point = new Point();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            wm.getDefaultDisplay().getRealSize(point);
        } else {
            wm.getDefaultDisplay().getSize(point);
        }
        return point;
    }

    private static String getSystemProperty(final String name) {
        String prop = getSystemPropertyByShell(name);
        if (!TextUtils.isEmpty(prop)) return prop;
        prop = getSystemPropertyByStream(name);
        if (!TextUtils.isEmpty(prop)) return prop;
        if (Build.VERSION.SDK_INT < 28) {
            return getSystemPropertyByReflect(name);
        }
        return prop;
    }

    private static String getSystemPropertyByShell(final String propName) {
        String line;
        BufferedReader input = null;
        try {
            Process p = Runtime.getRuntime().exec("getprop " + propName);
            input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
            String ret = input.readLine();
            if (ret != null) {
                return ret;
            }
        } catch (IOException ignore) {
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException ignore) {/**/}
            }
        }
        return "";
    }

    private static String getSystemPropertyByStream(final String key) {
        try {
            Properties prop = new Properties();
            FileInputStream is = new FileInputStream(
                    new File(Environment.getRootDirectory(), "build.prop")
            );
            prop.load(is);
            return prop.getProperty(key, "");
        } catch (Exception ignore) {/**/}
        return "";
    }

    private static String getSystemPropertyByReflect(String key) {
        try {
            Class<?> clz = Class.forName("android.os.SystemProperties");
            Method getMethod = clz.getMethod("get", String.class, String.class);
            return (String) getMethod.invoke(clz, key, "");
        } catch (Exception e) {/**/}
        return "";
    }

    public static String getIPAddress(final boolean useIPv4) {
        try {
            Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
            LinkedList<InetAddress> adds = new LinkedList<>();
            while (nis.hasMoreElements()) {
                NetworkInterface ni = nis.nextElement();
                // To prevent phone of xiaomi return "10.0.2.15"
                if (!ni.isUp() || ni.isLoopback()) continue;
                Enumeration<InetAddress> addresses = ni.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    adds.addFirst(addresses.nextElement());
                }
            }
            for (InetAddress add : adds) {
                if (!add.isLoopbackAddress()) {
                    String hostAddress = add.getHostAddress();
                    boolean isIPv4 = hostAddress.indexOf(':') < 0;
                    if (useIPv4) {
                        if (isIPv4) return hostAddress;
                    } else {
                        if (!isIPv4) {
                            int index = hostAddress.indexOf('%');
                            return index < 0
                                    ? hostAddress.toUpperCase()
                                    : hostAddress.substring(0, index).toUpperCase();
                        }
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return "";
    }

    public static void reboot() {
        BufferedReader input = null;
        try {
            Process p = Runtime.getRuntime().exec("reboot");
            input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
            String ret = input.readLine();
            if (ret != null) {
                return;
            }
        } catch (IOException ignore) {
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException ignore) {/**/}
            }
        }

    }
}
